/**************************************************************************
 *
 * Copyright (C) 2007 University of California, Los Angeles.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 *************************************************************************/

/**
 * 
 */
package edu.ucla.cs.typecast.cache2;

import java.io.IOException;
import java.io.Serializable;
import java.util.Date;
import java.util.Hashtable;

import edu.ucla.cs.typecast.net.EndPoint;
import edu.ucla.cs.typecast.net.EndPointListener;
import edu.ucla.cs.typecast.net.EndPointListenerFactory;
import edu.ucla.cs.typecast.net.NetUtil;
import edu.ucla.cs.typecast.rmi.Fact;
import edu.ucla.cs.typecast.rmi.Future;
import edu.ucla.cs.typecast.rmi.TypeCastClient;
import edu.ucla.cs.typecast.rmi.TypeCastServer;
import edu.ucla.cs.typecast.rmi.server.GUIDGenerator;
import edu.ucla.cs.typecast.scope.NetScope;
import edu.ucla.cs.typecast.scope.Scope;

/**
 *
 * @date Aug 21, 2007
 */
public class CacheRequestor implements ContentSource {
	private EndPoint serviceEndPoint; 
	private EndPoint contentSourceEndPoint; 

	private Hashtable<Object, CacheRequest> cacheRequest = new Hashtable<Object, CacheRequest>();  
	private Hashtable<String, CacheRequest> idRequest = new Hashtable<String, CacheRequest>(); 
	
	
	CacheRequestor(EndPoint serviceEndPoint) throws IOException { 
		this.serviceEndPoint = serviceEndPoint; 
		TypeCastServer tserver = new TypeCastServer(null); 
		contentSourceEndPoint = tserver.getEndPoint(); 
		tserver.export(ContentSource.class, this); 
	}

	public synchronized void requestCache(Scope scope, Class[] types, Object serviceObject, int timeout) throws IOException{
		if (! (serviceObject instanceof Serializable)) { 
			throw new RuntimeException(serviceObject.getClass() + " is not Serializable"); 
		}
		
		CacheRequest request = new CacheRequest(); 
		request.setGuid(GUIDGenerator.createGUID(serviceObject)); 
		request.setImplementationClass(serviceObject.getClass()); 
		request.setScope(scope); 
		request.setServiceObject(serviceObject); 
		request.setExpire(new Date(new Date().getTime() + timeout * 1000)); 
		request.setTypes(types); 
		cacheRequest.put(serviceObject, request); 
		idRequest.put(request.getGuid(), request); 
		
		TypeCastClient tclient = new TypeCastClient(this.serviceEndPoint); 
		tclient.setScope(scope); 
		CacheService cacheService = (CacheService)tclient.getTypeCastInvocationHandler(CacheService.class); 
		CacheObjectDescription desp = new CacheObjectDescription(); 
		desp.setGUID(request.getGuid()); 
		desp.setImplementationClass(request.getImplementationClass()); 
		desp.setTypes(request.getTypes()); 		
		desp.setTimeout(request.getTimeoutInSeconds()); 
		cacheService.requestCache(this.contentSourceEndPoint, desp); 
	}
	
	public void withdrawRequest(Object serviceObject) { 
		CacheRequest request = cacheRequest.remove(serviceObject); 
		if (request != null)
			idRequest.remove(request.getGuid()); 
	}
	
	public void requestContent(EndPoint contentCacheEndPoint,  String objectID) throws IOException { 
		CacheRequest request = idRequest.get(objectID);
		if (request != null) { 
			CacheObjectDescription desp = new CacheObjectDescription(); 
			desp.setGUID(request.getGuid()); 
			desp.setImplementationClass(request.getImplementationClass()); 
			desp.setTypes(request.getTypes()); 		
			desp.setTimeout(request.getTimeoutInSeconds()); 			
			TypeCastClient tclient = new TypeCastClient(contentCacheEndPoint); 
			ContentCacheService contentCache = (ContentCacheService)tclient.getTypeCastInvocationHandler(ContentCacheService.class); 			
			contentCache.cacheObject(this.contentSourceEndPoint, desp, request.getContent()); 
		}
	}
	
	public Future<byte[]> requestContent(String objectID) throws IOException { 
		CacheRequest request = idRequest.get(objectID);
		if (request != null) { 
			return new Fact<byte[]>(request.getContent());
		}
		return null; 
	}

}
